/*
 * @(#)FindDocumentsRunner.java
 * Date 2013-08-31
 * Version 1.0
 * Author Jim Horner
 * Copyright (c)2012
 */


package us.hornerscorners.lamppost.registry.query.es;

import java.util.HashMap;
import java.util.Map;

import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;

import us.hornerscorners.lamppost.ihecommon.config.IHEConfig;

import us.hornerscorners.lamppost.ihecommon.service.ElasticSearchSource;

import us.hornerscorners.lamppost.model.common.PersistableModelType;

import us.hornerscorners.lamppost.registry.constant.QueryField;
import us.hornerscorners.lamppost.registry.constant.QuerySlotName;

import us.hornerscorners.lamppost.registry.model.QueryRequest;

import us.hornerscorners.lamppost.registry.transformer.model.CodedElementTransformer;
import us.hornerscorners.lamppost.registry.transformer.model.PatientIdentifierTransformer;


/**
 * Class description
 *
 *
 * @version        v1.0, 2013-08-31
 * @author         Jim Horner
 */
public class FindDocumentsRunner extends AbstractQueryRunner {

    /**
     * Constructs ...
     *
     *
     * @param config
     * @param elasticSearchSource
     * @param codedElementTransformer
     * @param patientIdentifierTransformer
     */
    public FindDocumentsRunner(
            IHEConfig config, ElasticSearchSource elasticSearchSource,
            CodedElementTransformer codedElementTransformer,
            PatientIdentifierTransformer patientIdentifierTransformer) {

        super(config, elasticSearchSource, codedElementTransformer,
              patientIdentifierTransformer);
    }

    /**
     * Method description
     *
     *
     * @param request
     *
     * @return
     */
    @Override
    public Map<PersistableModelType, QueryBuilder> createQuery(QueryRequest request) {

        Map<PersistableModelType, QueryBuilder> result = new HashMap<>();

        BoolQueryBuilder query = QueryBuilders.boolQuery();

        result.put(PersistableModelType.DocumentEntry, query);

        // availability status (required)
        query.must(createStringQuery(request, QuerySlotName.XDSDocumentEntryStatus,
                                     QueryField.DocumentEntryAvailabilityStatus));

        // patient id
        if (request.hasValues(QuerySlotName.XDSDocumentEntryPatientId)) {

            query.must(createPatientIdentifierQuery(request,
                    QuerySlotName.XDSDocumentEntryPatientId,
                    QueryField.DocumentEntryPatientIdRoot,
                    QueryField.DocumentEntryPatientIdExtension));
        }

        // class code
        if (request.hasValues(QuerySlotName.XDSDocumentEntryClassCode)) {

            query.must(createCodedElementQuery(request,
                                               QuerySlotName.XDSDocumentEntryClassCode,
                                               QueryField.DocumentEntryClassCodeCode,
                                               QueryField.DocumentEntryClassCodeScheme));
        }

        if (request.hasValues(QuerySlotName.XDSDocumentEntryClassCodeScheme)) {

            query.must(createStringQuery(request,
                                         QuerySlotName.XDSDocumentEntryClassCodeScheme,
                                         QueryField.DocumentEntryClassCodeScheme));
        }

        // type code
        if (request.hasValues(QuerySlotName.XDSDocumentEntryTypeCode)) {

            query.must(createCodedElementQuery(request,
                                               QuerySlotName.XDSDocumentEntryTypeCode,
                                               QueryField.DocumentEntryTypeCodeCode,
                                               QueryField.DocumentEntryTypeCodeScheme));
        }

        if (request.hasValues(QuerySlotName.XDSDocumentEntryTypeScheme)) {

            query.must(createStringQuery(request,
                                         QuerySlotName.XDSDocumentEntryTypeScheme,
                                         QueryField.DocumentEntryTypeCodeScheme));
        }

        // practice setting code
        if (request.hasValues(QuerySlotName.XDSDocumentEntryPracticeSettingCode)) {

            query.must(
                createCodedElementQuery(
                    request, QuerySlotName.XDSDocumentEntryPracticeSettingCode,
                    QueryField.DocumentEntryPracticeSettingCodeCode,
                    QueryField.DocumentEntryPracticeSettingCodeScheme));
        }

        if (request.hasValues(QuerySlotName.XDSDocumentEntryPracticeSettingCodeScheme)) {

            query.must(
                createStringQuery(
                    request, QuerySlotName.XDSDocumentEntryPracticeSettingCodeScheme,
                    QueryField.DocumentEntryPracticeSettingCodeScheme));
        }

        // creation time
        if (request.hasValues(QuerySlotName.XDSDocumentEntryCreationTimeFrom)
                || request.hasValues(QuerySlotName.XDSDocumentEntryCreationTimeTo)) {

            query.must(createTimeQuery(request,
                                       QuerySlotName.XDSDocumentEntryCreationTimeFrom,
                                       QuerySlotName.XDSDocumentEntryCreationTimeTo,
                                       QueryField.DocumentEntryCreationTime));
        }

        // service start
        if (request.hasValues(QuerySlotName.XDSDocumentEntryServiceStartTimeFrom)
                || request.hasValues(QuerySlotName.XDSDocumentEntryServiceStartTimeTo)) {

            query.must(
                createTimeQuery(
                    request, QuerySlotName.XDSDocumentEntryServiceStartTimeFrom,
                    QuerySlotName.XDSDocumentEntryServiceStartTimeTo,
                    QueryField.DocumentEntryServiceIntervalStart));
        }

        // service stop
        if (request.hasValues(QuerySlotName.XDSDocumentEntryServiceStopTimeFrom)
                || request.hasValues(QuerySlotName.XDSDocumentEntryServiceStopTimeTo)) {

            query.must(createTimeQuery(request,
                                       QuerySlotName.XDSDocumentEntryServiceStopTimeFrom,
                                       QuerySlotName.XDSDocumentEntryServiceStopTimeTo,
                                       QueryField.DocumentEntryServiceIntervalStop));
        }

        // healthcare facility type code
        if (request.hasValues(QuerySlotName.XDSDocumentEntryHealthcareFacilityTypeCode)) {

            query.must(
                createCodedElementQuery(
                    request, QuerySlotName.XDSDocumentEntryHealthcareFacilityTypeCode,
                    QueryField.DocumentEntryHealthcareFacilityTypeCodeCode,
                    QueryField.DocumentEntryHealthcareFacilityTypeCodeScheme));
        }

        if (request.hasValues(
                QuerySlotName.XDSDocumentEntryHealthcareFacilityTypeCodeScheme)) {

            query.must(
                createStringQuery(
                    request,
                    QuerySlotName.XDSDocumentEntryHealthcareFacilityTypeCodeScheme,
                    QueryField.DocumentEntryHealthcareFacilityTypeCodeScheme));
        }

        // event code
        if (request.hasValues(QuerySlotName.XDSDocumentEntryEventCodeList)) {

            query.must(
                createCodedElementQuery(
                    request, QuerySlotName.XDSDocumentEntryEventCodeList,
                    QueryField.DocumentEntryEventCodesCode,
                    QueryField.DocumentEntryEventCodesScheme));
        }

        if (request.hasValues(QuerySlotName.XDSDocumentEntryEventCodeListScheme)) {

            query.must(
                createStringQuery(
                    request, QuerySlotName.XDSDocumentEntryEventCodeListScheme,
                    QueryField.DocumentEntryEventCodesScheme));
        }

        // confidentiality code
        if (request.hasValues(QuerySlotName.XDSDocumentEntryConfidentialityCode)) {

            query.must(
                createCodedElementQuery(
                    request, QuerySlotName.XDSDocumentEntryConfidentialityCode,
                    QueryField.DocumentEntryConfidentialityCodesCode,
                    QueryField.DocumentEntryConfidentialityCodesScheme));
        }

        if (request.hasValues(QuerySlotName.XDSDocumentEntryConfidentialityCodeScheme)) {

            query.must(
                createStringQuery(
                    request, QuerySlotName.XDSDocumentEntryConfidentialityCodeScheme,
                    QueryField.DocumentEntryConfidentialityCodesScheme));
        }

        // author person
        if (request.hasValues(QuerySlotName.XDSDocumentEntryAuthorPerson)) {

            query.must(createStringQuery(request,
                                         QuerySlotName.XDSDocumentEntryAuthorPerson,
                                         QueryField.DocumentEntryAuthorsPerson));
        }

        // format code
        if (request.hasValues(QuerySlotName.XDSDocumentEntryFormatCode)) {

            query.must(createCodedElementQuery(request,
                                               QuerySlotName.XDSDocumentEntryFormatCode,
                                               QueryField.DocumentEntryFormatCodeCode,
                                               QueryField.DocumentEntryFormatCodeScheme));
        }

        if (request.hasValues(QuerySlotName.XDSDocumentEntryFormatCodeScheme)) {

            query.must(createStringQuery(request,
                                         QuerySlotName.XDSDocumentEntryFormatCodeScheme,
                                         QueryField.DocumentEntryFormatCodeScheme));
        }

        return result;
    }
}
